/*********************************************************************************
 *      Copyright:  (C) 2025 TBW
 *                  All rights reserved.
 *
 *       Filename:  sqlite.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(19/05/25)
 *         Author:  huang zixiao <2027838269@qq.com>
 *      ChangeLog:  1, Release initial version on "19/05/25 15:52:12"
 *                 
 ********************************************************************************/

#include "sqlite.h"
#include "logger.h"

int db_init(db_info_t *db_info)
{

    int              rv;
    char             sql[128];

	//if file already exist, just open
	if( 0 == access(db_info->sqlite_filename, F_OK) )
	{
		if( SQLITE_OK != sqlite3_open(db_info->sqlite_filename, &(db_info->db)) )
		{
			log_error("open database file '%s' failure\n", db_info->sqlite_filename);
			//sqlite3_close(db_info->db);
			return -1;
		}
		log_info("open database file '%s' ok\n", db_info->sqlite_filename);
		return 0;
	}

    //if file are not exist, open file and create table
    rv = sqlite3_open(db_info->sqlite_filename, &(db_info->db));
    if(rv != SQLITE_OK)
    {
        log_error("cannot open %s:%s\n", db_info->sqlite_filename, sqlite3_errmsg(db_info->db));
        //sqlite3_close(db_info->db);
        return -1;
    }
    log_debug("open %s successfully!\n", db_info->sqlite_filename);

    //create table
    memset(sql, 0, sizeof(sql));
	snprintf(sql, sizeof(sql), "CREATE TABLE %s(packet BLOB);", db_info->table_name);
    rv = sqlite3_exec(db_info->db, sql, NULL, NULL, &(db_info->err_msg));
    if(rv != SQLITE_OK)
    {
        log_error("sql error:%s\n", db_info->err_msg);
        sqlite3_free(db_info->err_msg);
		sqlite3_close(db_info->db);
        return -1;
    }

	log_debug("create table %s successfully\n", db_info->table_name);

    return 0;
}


int save_in_db(db_info_t *db_info, void *buf, int buf_size)
{
    int          			 rv;
    char         		 	 sql[128] = {0};
	sqlite3_stmt    	  	*stat = NULL;

	if(!db_info || !buf || buf_size<=0 )
	{
		log_error("invalid argument!\n");
		return -1;
	}

	if( !db_info->db )
    {
        log_error("sqlite database not opened\n");
        return -2;
    }

    snprintf(sql, sizeof(sql), "INSERT INTO %s(packet) VALUES(?)", db_info->table_name);
	rv = sqlite3_prepare_v2(db_info->db, sql, -1, &stat, NULL);
	if(SQLITE_OK!=rv || !stat)
    {
        log_error("blob add sqlite3_prepare_v2 failure\n");
        rv = -2;
        goto OUT;
    }

    if( SQLITE_OK != sqlite3_bind_blob(stat, 1, buf, buf_size, NULL) )
    {
        log_error("blob add sqlite3_bind_blob failure\n");
        rv = -3;
        goto OUT;
    }

    rv = sqlite3_step(stat);
    if( SQLITE_DONE!=rv && SQLITE_ROW!=rv )
    {
        log_error("blob add sqlite3_step failure\n");
        rv = -4;
        goto OUT;
    }

OUT:
    sqlite3_finalize(stat);

    if( rv < 0 )
        log_error("add new blob packet into database failure, rv=%d\n", rv);
    else
        log_info("add new blob packet into database ok\n");

    return rv;
}

int get_data_in_db(db_info_t *db_info, void *buf, int size, int *bytes)
{
    int              rv;
    char             sql[128] = {0};
	const void        *blob_ptr;
	sqlite3_stmt      *stat = NULL;

	if(!db_info || !buf || size<=0)
	{
		log_error("invalid argument\n");
		return -1;
	}
	
	if( !db_info->db )
    {
        log_error("sqlite database not opened\n");
        return -2;
    }

	//memset(callback_arg, 0, sizeof(callback_arg));

	snprintf(sql, sizeof(sql), "SELECT packet FROM %s WHERE rowid = (SELECT rowid FROM %s LIMIT 1);",
			db_info->table_name, db_info->table_name);
	rv = sqlite3_prepare_v2(db_info->db, sql, -1, &stat, NULL);
    if(SQLITE_OK!=rv || !stat)
    {
        log_error("firehost sqlite3_prepare_v2 failure\n");
        rv = -3;
        goto out;
    }

	rv = sqlite3_step(stat);
    if( SQLITE_DONE!=rv && SQLITE_ROW!=rv )
    {
        log_error("firehost sqlite3_step failure\n");
        rv = -5;
        goto out;
    }

	blob_ptr = sqlite3_column_blob(stat, 0);
    if( !blob_ptr )
    {
        rv = -6;
        goto out;
    }

	*bytes = sqlite3_column_bytes(stat, 0);
    if( *bytes > size )
    {
        log_error("blob packet bytes[%d] larger than bufsize[%d]\n", *bytes, size);
        *bytes = 0;
        rv = -1;
    }

	memcpy(buf, blob_ptr, *bytes);
    rv = 0;

out:
	sqlite3_finalize(stat);
	return rv;
}

int delete_1st_db(db_info_t *db_info)
{
    int                   rv;
    char                  sql[128] = {0};

	if(!db_info)
	{
		log_error("invalid argument\n");
		return -1;
	}

	if(!db_info->db)
	{
		log_error("sqlite database not opened\n");
		return -2;
	}

    snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE rowid = (SELECT rowid FROM %s LIMIT 1);",
			db_info->table_name, db_info->table_name);

    rv = sqlite3_exec(db_info->db, sql, NULL, NULL, &(db_info->err_msg));
    if(rv != SQLITE_OK)
    {
        log_error("sql error:%s\n", db_info->err_msg);
        sqlite3_free(db_info->err_msg);
        return -1;
    }
    return 0;
}

int callback(void *arg, int num_columns, char **value, char **name_columus)
{

    callback_arg_t   *callback_arg = (callback_arg_t *)arg;//Type matching and conversion


    callback_arg->sqlite_have_data = 1;

	/* table type: values(data:text); */
	if( strlen(value[0]) > sizeof(callback_arg->data_in_db) )
	{
		log_error("the size of database's data more than object buf size\n");
		return -1;
	}
	snprintf(callback_arg->data_in_db, sizeof(callback_arg->data_in_db), "%s", value[0]);


	
	/*  table type: values(time:text, device:text, temperature:text);*/
	/*
    for(i=0; i<num_columns; i++)
    {
        if(i == 0)
        {
            snprintf(time, sizeof(time), "%s", value[i]);
        }
        if(i == 1)
        {
            snprintf(device, sizeof(device), "%s", value[i]);
        }
        if(i == 2)
        {
            snprintf(temperature, sizeof(temperature), "%s", value[i]);
        }
    }
    memset(line_data, 0, sizeof(line_data));
    snprintf(line_data, sizeof(line_data), "%s/%s/%s/", time, device, temperature);
    snprintf(callback_arg->upload_sqlite_data, sizeof(callback_arg->upload_sqlite_data), "%s", line_data);
	*/

    return 0;
}
